
import re
from threading import Timer

class TarjanCommandParser (object):
    def __init__(self, table = {}, timeout = 3):
        self.table = table
        self.timeout = timeout
        self.current_cmd = ''

    def reset_timer (self):
        if self.__dict__.get('timer'):
            self.timer.cancel()
        self.timer = Timer(self.timeout, self.timer_expired)
        return self.timer

    def timer_expired(self):
        self.current_cmd = ''
        self.timer = None

    def clear(self):
        self.current_cmd = ''

    def parse_key(self, key):
        self.current_cmd += key

        #print '===', repr(self.current_cmd),
        for cmd, action in self.table.items():
            #print repr(cmd), 
            matches = re.match(cmd, self.current_cmd)
            if matches:
                self.current_cmd = ''
                arguments = list(action[1:])
                arguments.extend(matches.groups())
                #print ''
                action[0](*arguments)
                break

        if (self.current_cmd):
            self.reset_timer().start()
            #print ''

if __name__ == '__main__':

    import operator

    run = True

    def getch():
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

    def end_program():
        global run
        run = False

    def say(str):
        print str

    def say2(func, a, b):
        print repr(func(int(a), int(b)))

    command_table = {
        'a': (say, 'hest'),
        'q': (end_program,),
        'dd': (say, 'laks'),
        'dw': (say, 'giraf'),
        'n(.+)\n': (say,),
        'x(\d+),(\d+)\n': (say2, operator.add)
    }

    parser = TarjanCommandParser(command_table)

    command_table['.*\x1b'] = (parser.clear,)
    command_table['.*H'] = (say, parser.current_cmd,)

    while run:
        #print '>>', repr(parser.current_cmd)
        ch = getch()
        parser.parse_key(ch)

